import RescacheMgr from "../../framework/inc/rescachemgr";
import * as THREE from "../../../three.module";

const STAR_CNT = 1000;                  //星星个数
const SHINNING_SPEED = 10 / (10 ** 4);  //闪烁速度
const STAR_SIZE = 1;                  //星星大小

let pos = [];
let colors = [];
let sizes = [];

const genRandomSphereP = function (radius) {
    //how to gen points in sphere
    //https://www.zhihu.com/question/26579222

    let u = Math.random(0, 1);
    let v = Math.random(0, 1);
    let theta = u * Math.PI * 2;

    let phi = Math.acos(2 * v - 1);
    let x = radius * Math.sin(theta) * Math.sin(phi);
    let y = radius * Math.cos(theta) * Math.sin(phi);
    let z = radius * Math.cos(phi);

    let ret = [x, y, z];
    return ret;
}

export default class EffStar extends THREE.Object3D {
    constructor(texture, radius) {
        super();
        let inc = RescacheMgr.getInstance();
        let material_shader = new THREE.ShaderMaterial(
            {
                uniforms: this.init_uniform(texture),
                vertexShader: inc.getGLSL("star_vertex"),
                fragmentShader: inc.getGLSL("star_fragment"),
                blending: THREE.AdditiveBlending,
                // depthTest: false,
                transparent: true,
                vertexColors: true
            }
        )
        let geometry_buffer = new THREE.BufferGeometry();
        let color = new THREE.Color();

        let ranpos;
        for (let i = 0; i < STAR_CNT; i++) {
            ranpos = genRandomSphereP(radius);
            pos.push(ranpos[0]);
            pos.push(ranpos[1]);
            pos.push(ranpos[2]);
            color.setHSL(i / STAR_CNT, 1.0, 0.5);
            colors.push(color.r, color.g, color.b);
            sizes.push(STAR_SIZE);
        }
        geometry_buffer.setAttribute("position", new THREE.Float32BufferAttribute(pos, 3));
        geometry_buffer.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
        geometry_buffer.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));

        let particle = new THREE.Points(geometry_buffer, material_shader);
        this.add(particle);
        this._geometry = geometry_buffer;
    }

    init_uniform(texture) {
        let uniform = {
            texture: {
                value: texture
            }
        };
        return uniform;
    }

    update() {
        if (this._geometry) {
            let time = Date.now() + 0.005;
            this.rotation.z += SHINNING_SPEED;
            let sizes = this._geometry.attributes.size.array;
            for (let i = 1; i < STAR_CNT; i++) {
                sizes[i] = STAR_SIZE + 0.1;       //todo shinning
            }
            this._geometry.attributes.size.needsUpdate = true;
        }
    }
}